#ifndef __SLOTHTTPD_HTTP_STATUS_HPP__
#define __SLOTHTTPD_HTTP_STATUS_HPP__

#include <slothttpd/types.hpp>
#include <slothttpd/http/http.hpp>
#include <slothttpd/http/header/responce.hpp>

#include <string>
#include <utility>
#include <vector>

#include <boost/lexical_cast.hpp>
#include <boost/asio/buffer.hpp>

namespace slothttpd {
namespace http {
namespace status {

struct status_type
{
    inline status_type(int c, const char *s) :
        code(c),
        status_line(boost::lexical_cast<std::string>(c) + " " + std::string(s))
    {
        buffers.push_back(boost::asio::buffer(http::http11));
        buffers.push_back(boost::asio::buffer(status_line));
        buffers.push_back(boost::asio::buffer(http::crlf));
        
        // TODO: add Date header
        buffers.push_back(boost::asio::buffer(http::headers::response::connection_close));
        buffers.push_back(boost::asio::buffer(http::crlf));
        buffers.push_back(boost::asio::buffer(body));
    }
    
    inline bool operator==(const status_type &rhv) const
    {
        return code == rhv.code;
    }
    
    inline bool operator!=(const status_type &rhv) const
    {
        return code != rhv.code;
    }
    
    inline const_buffer_range_t buffer_range() const
    {
        auto first = const_cast<boost::asio::const_buffer*>(buffers.data());
        return const_buffer_range_t(first, first + buffers.size());
    }
    
    const int code;
    // use mutable here, so we can deal without cpp file and all duplications
    mutable std::string status_line;
    mutable std::string body = "<html><body><h1><b>" + status_line + "</b></h1></body></html>\n";
    
private:
    mutable std::vector<boost::asio::const_buffer> buffers;
};

// Informational 1xx
const status_type continue_ = { 100, "Continue" };
const status_type switching_protocols = { 101, "Switching Protocols" };

// Successful 2xx
const status_type ok = { 200, "OK" };
const status_type created = { 201, "Created" };
const status_type accepted = { 202, "Accepted" };
const status_type non_authoritative_information = { 203, "Non-Authoritative Information" };
const status_type no_content = { 204, "No Content" };
const status_type reset_content = { 205, "Reset Content" };
const status_type partial_content = { 206, "Partial Content" };

// Redirection 3xx
const status_type multiple_choices = { 300, "Multiple Choices" };
const status_type moved_permanently = { 301, "Moved Permanently" };
const status_type found = { 302, "Found" };
const status_type see_other = { 303, "See Other" };
const status_type not_modified = { 304, "Not Modified" };
const status_type use_proxy = { 305, "Use Proxy" };
const status_type temporary_redirect = { 307, "Temporary Redirect" };

// Client Error 4xx
const status_type bad_request = { 400, "Bad Request" };
const status_type unauthorized = { 401, "Unauthorized" };
const status_type payment_required = { 402, "Payment Required" };
const status_type forbidden = { 403, "Forbidden" };
const status_type not_found = { 404, "Not Found" };
const status_type method_not_allowed = { 405, "Method Not Allowed" };
const status_type not_acceptable = { 406, "Not Acceptable" };
const status_type proxy_authentication_required = { 407, "Proxy Authentication Required" };
const status_type request_timeout = { 408, "Request Timeout" };
const status_type conflict = { 409, "Conflict" };
const status_type gone = { 410, "Gone" };
const status_type length_required = { 411, "Length Required" };
const status_type precondition_failed = { 412, "Precondition Failed" };
const status_type request_entity_too_large = { 413, "Request Entity Too Large" };
const status_type request_uri_too_long = { 414, "Request-URI Too Long" };
const status_type unsupported_media_type = { 415, "Unsupported Media Type" };
const status_type requested_range_not_satisfiable = { 416, "Requested Range Not Satisfiable" };
const status_type expectation_failed = { 417, "Expectation Failed" };

// Server Error 5xx
const status_type internal_server_error = { 500, "Internal Server Error" };
const status_type not_implemented = { 501, "Not Implemented" };
const status_type bad_gateway = { 502, "Bad Gateway" };
const status_type service_unavailable = { 503, "Service Unavailable" };
const status_type gateway_timeout = { 504, "Gateway Timeout" };
const status_type http_version_not_supported = { 505, "HTTP Version Not Supported" };

}
}
}

#endif
